package com.baizhi.cmfz.aspect;

import com.mysql.jdbc.TimeUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Configuration
@Aspect
public class CacheAspect {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 1.判断缓存里有没有想要的数据
     * 2.如果有 把缓存的结果返回
     * 3.如果没有 查询数据库 将数据放入缓存
     * @return
     */
    //添加缓存 使用环绕增强 需要放行操作 可以获取方法的返回值
    @Around("@annotation(com.baizhi.cmfz.annottation.AddCacheAnnotation)")
    public  Object addCache(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        //1.判断缓存中有没有数据
        //2.没有的话 查询数据库  结果放入缓存
        //3.有的话 从缓存中获取数据 直接返回
        //字符串拼接 方法名和形参列表  做hashKey 键
        StringBuilder stringBuilder=new StringBuilder();
        //获取方法名称
        String methodName = proceedingJoinPoint.getSignature().getName();
        //拼接方法名
        stringBuilder.append(methodName);
        //获取类名称
        String className = proceedingJoinPoint.getTarget().getClass().getName();
       //获取方法中的参数
        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            //拼接参数
            stringBuilder.append(arg);
        }
        //hash 键
        String hashKey = stringBuilder.toString();
        System.out.println("类名"+className);
        System.out.println("方法名称"+methodName);
        HashOperations hashOperations = redisTemplate.opsForHash();
        //先从缓存中获取数据
        Object result = hashOperations.get(className, hashKey);

        if(result == null){
            //缓存中没有 查数据库 结果放入缓存  放行
            //获取到方法的返回值 //放行去查询数据库
            result = proceedingJoinPoint.proceed();
            System.out.println(result+"方法返回值");
            Map map=new HashMap();
            map.put(hashKey,result);
            //放入数据库
            hashOperations.putAll(className,map);
            System.out.println("查询数据库----");
            //设置失效时间 expire 参数1 要设置的key 参数2 时间数 参数3 单位
            redisTemplate.expire(className,10, TimeUnit.SECONDS);
        }else {
            System.out.println(result+"缓存数据");
        }

        return  result;
    }

    /**
     * 使用前置增强  执行增删改清除缓存
     * @param joinPoint
     */
    @Before("@annotation(com.baizhi.cmfz.annottation.DeleteCacheAnnotation)")
    public  void  deleteCache(JoinPoint joinPoint){
        //获取类名
        String className = joinPoint.getTarget().getClass().getName();
        //根据类名  删除缓存
        Boolean delete = redisTemplate.delete(className);
        System.out.println("删除缓存-----------"+delete);
    }
}
